<template>
  <n-drawer width="1500px" :close-on-esc="false" :mask-closable="false">
    <n-drawer-content title="大语言模型推理">
        <n-grid :x-gap="20"> 
          <n-grid-item :span="6">
            <n-form ref="promptFormRef">
              <n-form-item label="推理方案名称">
                <n-select  :options="promptOptions" label-field="promptTitle" value-field="promptContent" :on-update:value="updatePromptTemplate"></n-select>
              </n-form-item>

              <n-form-item label="提示词模板">
                <n-input v-model:value="promptTemplate"
                         style="height: 400px" type="textarea"
                         ></n-input>
              </n-form-item>



            </n-form>
          </n-grid-item>
          <n-grid-item :span="18">
            <n-space justify="space-between" style="margin-bottom: 5px;">
              <n-space>
                <n-checkbox v-model:checked="skipFlag">跳过已完成推理</n-checkbox>
                <n-gradient-text  :size="18" type="info" v-if="checkedRowKeysRef">
                  选中{{  checkedRowKeysRef.length }}行
                </n-gradient-text>

                <progressLite
                  v-if="taskStatus.totalNum>0"
                  :totalNum="taskStatus.totalNum"
                  :successNum="taskStatus.successNum"
                  :failNum="taskStatus.failNum"
                  :pauseFlag="pauseFlag"
                  :pauseTask="pauseTask"
                  :continueTask="continueTask"
                  :cancelTask = "cancelTask"></progressLite>

              </n-space>
              <n-button size="small" type="primary" @click="batchReasonPrompt">批量推理</n-button>
            </n-space>
            <n-scrollbar :style="{ height: clientHeight - (layoutHeaderHeight  + tabsHeight + 110) + 'px'}">


              <n-data-table
                :data="bizData"
                :columns="createColumns"
                :checked-row-keys="checkedRowKeysRef"
                @update:checked-row-keys="handleCheck"
                :bordered="true"
                :loading="tableLoading"
                :row-key="(row)=>{
                  return row.id
                }">
              </n-data-table>
            </n-scrollbar>
          </n-grid-item>
        </n-grid>
        <template #footer>
          <n-button type="warning" style="margin-right: 20px;" @click="props.closeAction">
            关闭
          </n-button>
          <n-button ref="batchReason" type="primary" @click="saveResultFunction(bizData)">
            保存结果
          </n-button>
        </template>
    </n-drawer-content>
  </n-drawer>
</template>
<script setup lang="ts">
import {h, onMounted, ref, watch} from "vue"
//@ts-ignore
import {storeToRefs} from "pinia"
import {useSystemStore} from "@/store/modules/useSystemStore"
import {promptControllerApi} from "@/api/prompt/prompt.api";
import {SelectBaseOption} from "naive-ui/lib/select/src/interface";
import useClipboard from "vue-clipboard3";
import {NButton, NInput, NP, NText} from "naive-ui";
import {storyController} from "@/api/story/story.api";
import progressLite from '@/components/progress/ProgressLite.vue'

// 使用插件
const { toClipboard } = useClipboard();
let controller = new AbortController()
const bizData = ref([])
const story = ref(null)
const promptOptions = ref(null)
const promptTemplate = ref(null)
const batchReason = ref(null)
const checkedRowKeysRef = ref([])
const tableLoading = ref(false)
const skipFlag = ref(true)
const pauseFlag = ref(false)
const stopLoop = ref(false)
const currentTaskNum = ref(0)
const selectTemplate = ref(null)
const {
  clientHeight,
  layoutHeaderHeight,
  darkTheme,
  tabsHeight
} = storeToRefs(useSystemStore());

const handleCheck = (rowKeys: [])=> {
  checkedRowKeysRef.value = rowKeys
}

const getPromptInfo = ()=>{
  promptControllerApi.getGptPromptOption('custom_keyword').then((res)=>{
    if (res.code === 200){
      promptOptions.value = res.data
      // 增加默认选项
      promptOptions.value.unshift({
        promptTitle: 'EasyAI瞎推版本',
        promptContent: 'EasyAI瞎推版本提示词模板复杂,无法展示!',
        id: 999
      })
    }
  })
}

// 任务状态
const taskStatus = ref({
  successNum: 0,
  failNum: 0,
  totalNum: 0
})


const props = defineProps({
  storyId: {
    type:String,
    required: true
  },
  closeAction:{
    type: Function,
    required: true
  }
})


watch(() => props.storyId, (val) => {
  getPromptInfo()
  getStoryInfo()
  getStoryBoards()
})

const updatePromptTemplate = (value:string,option: SelectBaseOption )=>{
  promptTemplate.value = value
  selectTemplate.value = option
}


// 列表字段
const createColumns = [
  {
    type: 'selection'
  },
  {
    title: '序号',
    key: 'orderNum',
    width: 50
  },
  {
    title: '文本内容',
    key: 'content',
    width: 300,
    render(row: any) {
      return h(NP, {style: 'white-space: pre-line;'}, row.content)
    }
  },
  {
    title: '推理结果',
    key: 'prompt',
    width: 300,
    render(row: any) {
      return h(NInput, {style: 'white-space: pre-line;', value: row.prompt, type: 'textarea', rows: 3})
    }
  },
  {
    title: '操作',
    key: 'actions',
    width: 120,
    render(row:any) {
      return [h(
          NButton,
          {
            strong: true,
            tertiary: true,
            block: true,
            size: 'small',
            type: 'primary',
            onClick: () => reason(row.index)
          },
          { default: () => '文案推理' }
      ), h(
          NButton,
          {
            strong: true,
            tertiary: true,
            block: true,
            type: 'info',
            size: 'small',
            style: 'margin-top: 10px',
            onClick: () => copyPrompt(row.index)
          },
          { default: () => '提示词复制' }
      )]
    }
  }
]



onMounted(() => {
  getPromptInfo()
  getStoryInfo()
  getStoryBoards()
})



const getStoryBoards = () =>{
  tableLoading.value = true
  storyController.getStoryBoardList(props.storyId).then((res)=>{
    if (res.code === 200){
      bizData.value = []
      res.data.records.forEach((item:any,index:number)=>{
        let sentences = ''
        item.sentenceList.forEach((sentence:any)=>{
          sentences += sentence.content +"\n"
        })
        bizData.value.push({
          orderNum: item.orderNum,
          id: item.id,
          index: index,
          content: sentences,
          prompt : item.prompt
        })
      })
    }
  }).finally(()=>{
    tableLoading.value = false
  })
}
const getStoryInfo = () =>{
  storyController.getStoryById(props.storyId).then((res)=>{
    if (res.code === 200){
      story.value = res.data.story
    }
  })
}



const copyPrompt = async (index:number) => {
  if (promptTemplate.value === null || promptTemplate.value === ''){
    window.$message.warning("请选择提示词模板...")
    return
  }
  try {
    const text = promptTemplate.value.replace('{{content}}', bizData.value[index].content);
    // 复制
    await toClipboard(text ,batchReason.value.$el);
    window.$message.success("复制成功...")
    // 复制成功
  } catch (e) {
    console.log(e)
    window.$message.error("复制失败，请手动复制...")
  }
}


const batchReasonPrompt = () =>{
  if (checkedRowKeysRef.value.length === 0) {
    window.$message.info("请先选择推理的分镜!!")
    return
  }
  if (selectTemplate.value === null){
    window.$message.info("请选择推理方案名称...")
    return
  }
  stopLoop.value = false
  currentTaskNum.value = 0
  taskStatus.value = {
    successNum: 0,
    failNum: 0,
    totalNum: checkedRowKeysRef.value.length
  }
  for (const storyBoardId of checkedRowKeysRef.value) {
    if (stopLoop.value) {
      taskStatus.value.totalNum = 0
      taskStatus.value.successNum = 0
      taskStatus.value.failNum = 0
      pauseFlag.value = false
      break
    }
    const storyBoard = bizData.value.find((item: any) => item.id === storyBoardId)
    reason(storyBoard)
  }

}


const reason = async (storyBoard:any) => {
    if (selectTemplate.value.id == '999'){
      console.log('瞎推')
    }else {

    if (promptTemplate.value === null || promptTemplate.value === '') {
      window.$message.warning("请选择提示词模板...")
      return
    }
    const data = {
      prompt: promptTemplate.value.replace('{{content}}',storyBoard.content),
      signal: controller.signal
    }
    const onDownloadProgress = (event: any) => {
      const xhr = event.event.target
      const {responseText} = xhr
      storyBoard.prompt = responseText
    }
    await promptControllerApi.commonReason(data, onDownloadProgress)
  }
}


const pauseTask = () => {
  pauseFlag.value = true
}

const continueTask = () => {
  pauseFlag.value = false
}

const cancelTask = () => {
  stopLoop.value = true
}

</script>
